from flask import current_app
from flask import g,render_template, jsonify
from flask import request
from sqlalchemy import desc

from info import constants
from info import db
from info.models import News, User
from info.response import RET
from info.utils.image_storage import storage
from . import profile_blueprint
from info .utils.common import login_wrapps
from info.models import Category

# 个人中心功能实现逻辑思路
# 一页面展示
# 创建试图,并用蓝图装饰
@profile_blueprint.route('/')
@login_wrapps
def user():
# 1,模板继承
    #返回数据访问用户,所以吧user传入,点击用户进入个人中心如果
    #用户不登录就没办法访问。
    data = {
            'user' : g.user.to_login_dict() if g.user else None
            }
#渲染user.html页面用户中心页面
    return render_template('news/user.html',data = data)

# 二,基础资料

@profile_blueprint.route('/user_base_info',methods = ['GET','POST'])
@login_wrapps
def user_base_info():
    if request.method == 'GET':
        data ={
            'user' : g.user.to_dict()
        }
        return render_template('news/user_base_info.html',data = data)
#接受
    #接受要修改的数据,因为是从表单接受,所以用json数据
    signature = request.json.get('signature')
    nick_name = request.json.get('nick_name')
    gender = request.json.get('gender')

#验证
    #接受的数据是否非空
    if not all ([signature,nick_name,gender]):
        return jsonify(errno = RET.NODATA, errmsg = '数据不完整')
# post请求处理 修改内容
    user = g.user
    user.nick_name = nick_name
    user.signature = signature
    user.gender = gender
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno = RET.DBERR,errmsg = '数据库链接失败')
# 响应
    return  jsonify(errno = RET.OK,errmsg = '')


# 定义修改头像的试图,并且装饰蓝图
@profile_blueprint.route('/user_pic_info',methods = ['GET','POST'])
@login_wrapps
def user_pic_info():
#接受
    #获取请求方式并判断
    if request.method == 'GET':
        data = {
            'user' :g.user.to_login_dict()
        }
        #展示页面,渲染修改头像的主页面
        return render_template('news/user_pic_info.html',data = data)

    file = request.files.get('avatar')

#验证
    if not file:
        return jsonify(errno = RET.NODATA,errmsg = '请选择头像文件')

 #处理.保存图片,修改模型.导入,七牛云服务器.因为,要链接服务器
#所以',用捕获异常
    try:
        file_name = storage(file.read())
    except Exception as e:
        #吧错误信息输出到日志里
        current_app.loggre.error(e)
        return jsonify(errno = RET.THIRDERR, errmsg = '头像上传失败')
    #修改属性,创建修改属性的对象,用对象.头像路径 = 你要修改的文件名称
    user = g.user
    user.avatar_url = file_name
    #将上传好的头像保存到数据库,链接数据库用捕获异常
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno = RET.DBERR,errmsg = '头像保存失败')

#响应 响应成功的状态,和客户端需要打数据 用户调用定义好的to_login_dict方法
    return jsonify(errno = RET.OK,data = user.to_login_dict())

@profile_blueprint.route('/user_pass_info',methods = ['GET','POST'])
@login_wrapps
def user_pass_info():
    #验证请求方式,如果是GET方式展示修改密码页面
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')
#接受
    #接受客户端输入的数据
    old_password = request.json.get('old_password')
    new_password = request.json.get('new_password')
    new_password2 = request.json.get('new_password2')
#验证接受的数据是否非空
    if not all([old_password,new_password,new_password2]):
        return jsonify(errno = RET.NODATA,errmsg = '数据不完整')
    # 验证,两次输入的新密码是否不一致
    if new_password != new_password2:
        return jsonify(errno = RET.DATAERR,errmsg = '两次的新密码不一致')
    # 验证久密码是否正确,创建用户对象接受久密码
    user = g.user
    if not user.check_password(old_password):
        return jsonify(errno = RET.DATAERR,errmsg = '原密码错误')
    #修改完成,用户密码等于新密码,吧修改好的密码保存到数据库
    user.password = new_password
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno = RET.DBERR, errmsg = '保存新密码失败')

    return jsonify(errno = RET.OK, errmsg = '')

@profile_blueprint.route('/user_collection')
@login_wrapps
def user_collection():
    try:
        #定义页数,并且设默认值为1
        page = int(request.args.get('page', 1))
    except Exception as e:
        page = 1
    try:
        # 查询当前登录用户,收藏的新闻列表,排序,并且分页.调用constants.USER_COLLECTION_MAX_NEWS,False这个方法
        pagination = g.user.collection_news. \
            order_by(News.id.desc()). \
            paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        data = {
            'news_list' : [news.to_index_dict() for news in pagination.items],
            'total_pages' : pagination.pages,
            'page' : page
        }
    except Exception as  e:
        current_app.logger.error(e)
        #客户端请求的数据,如果出现异常那么返回的数据也是空的,因为,没查到数据.
        data = {
            'news_list' : [],
            'total_pages' : 0,
            'page' : 1
        }
        #如果出现异常,那么就展示,收藏页面,并吧客户端请求的数据传过去.
    return render_template('news/user_collection.html',data = data)




@profile_blueprint.route('/user_follow')
@login_wrapps
def user_follow():
   try:
        page = int(request.args.get('page' , 1))
   except Exception as  e:
       current_app.logger.error(e)
       page = 1
   try:
        pagination = g.user.authors.\
        order_by(User.id.desc()).\
        paginate(page,constants.USER_FOLLOWED_MAX_COUNT,False)
        data = {
            'author_list' : [author.to_dict() for author in pagination.items],

            'page' : page,
            'total_pages' : pagination.pages
        }
   except Exception as e:
       current_app.logger.error(e)
       data = {
           'author_list' : [],
           'page' : 1,
           'total_pages' : 0
       }
   return render_template('news/user_follow.html',data = data)

@profile_blueprint.route('/user_news_release', methods = ['GET','POST'])
@login_wrapps
def user_news_release():
    #判断请求方式
    if request.method =="GET":
        #引入新闻类,从新闻类中查询所有的新闻类,列表接受.
        #遍历查询到打所有新闻分类.然后吧遍历出来的新闻类调用to_dict方法形成新列表
        category_list = Category.query.all()
        category_list2 = [category.to_dict() for category in category_list]
        data = {# 返回数据,新生成好的新闻列表
            'category_list' : category_list2
        }
        return render_template('news/user_news_release.html',data = data)

#post请求方逻辑处理
#接受
    #接受用户请求的
    #发布新闻的标题
    title = request.form.get('title')
    #接受新闻类型的编号
    category_id = request.form.get('category_id')
    #摘要
    digest = request.form.get('digest')
    #新闻数量
    content = request.form.get('content')
    #接受上传的文件
    index_image = request.files.get('index_image')
    print([title,category_id,digest,content,index_image])
#验证
    # 验证接受的数据是否非空
    if not all ([title,category_id,digest,content,index_image]):
        return jsonify(errno = RET.NODATA,errmsg = '数据不完整')
    try:
        #查询分类新闻的编号.
        category = Category.query.get(category_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno = RET.DBERR,errmsg = '数据库连接失败')

    #验证新闻编号是否有效
    if category is None:
        return jsonify(errno = RET.DATAERR,errmsg = '无效的新闻编号')

    try:
        index_image_url = storage(index_image.read())
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno = RET.THIRDERR,errmsg = '上床图片失败')


    news = News()
    news.title = title
    news.source = g.user.nick_name
    news.digest = digest
    news.content = content
    news.index_image_url = index_image_url
    news.category_id = int(category_id)
    news.user_id = g.user.id
    db.session.add(news)
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno = RET.DBERR, errmsg = '新闻发布失败')

#4 响应
    return jsonify(errno = RET.OK,errmsg ='')

@profile_blueprint.route('/user_news_list')
@login_wrapps
def user_news_list():
    try:# 展示用户输入的页数,因为是展示所以请求方式是args默认为1
        page = int(request.args.get('page' , 1))
        #如果,页数没有改变默认为1
    except :
        page = 1

    try:#显示当前用户新闻列表的新闻ID 并且排序,时间早晚降序,分页,并且每页展示6条.
        pagination = g.user.news_list.order_by(News.id.desc()).paginate(page,6 ,False)
        # 如果显示,就返回客户需要的数据,
        data = {
            #遍历当前新闻列表,所有的内容,让变出来的新闻取调用定义好的to_release_dict()防范返回前端需要的数据
            'news_list' : [news.to_release_dict() for news in pagination.items],
            'page' : page,
            'total_page' : pagination.pages
        }
    except Exception as e:
        # 将错误输出到日志
        current_app.logger.error(e)
        # 如果出现异常,返回的数据将至空
        data = {
            'news_list' : [],
            'page' : 1,
            'total_page' : 0
        }
    return render_template('news/user_news_list.html',data = data)